package com.tianji.coupon.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.common.Result;
import com.tianji.coupon.mapper.ExchangeCodeMapper;
import com.tianji.coupon.pojo.Coupon;
import com.tianji.coupon.pojo.ExchangeCode;
import com.tianji.coupon.query.CouponQuery;
import com.tianji.coupon.service.ExchangeCodeService;
import com.tianji.common.utils.CodeUtil;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

import static com.tianji.common.constant.CouponCacheConstant.*;


/**
 * <p>
 * 兑换码 服务实现类
 * </p>
 *
 * @author 陈佳
 * @since 2024-08-29
 */
@Service
public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, ExchangeCode> implements ExchangeCodeService {

    private final StringRedisTemplate stringRedisTemplate;

    private final BoundValueOperations<String, String> serialOps;
    private final RedisTemplate redisTemplate;

    public ExchangeCodeServiceImpl(StringRedisTemplate stringRedisTemplate, @Qualifier("redisTemplate") RedisTemplate redisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.serialOps = stringRedisTemplate.boundValueOps(COUPON_CODE_SERIAL_KEY);
        this.redisTemplate = redisTemplate;
    }

    @Async("generateExchangeCodeExecutor")
    @Override
    public void asycGenerateCode(Coupon coupon) {
        Integer totalNum = coupon.getTotalNum();
        //获取redis的自增序列号
        Long result = serialOps.increment(totalNum);
        if(result == null){
            return;
        }
        int maxSerialNum = result.intValue();
        List<ExchangeCode> list = new ArrayList<>(totalNum);
        for(int serialNum = maxSerialNum - totalNum +1;serialNum <= maxSerialNum;serialNum++){
            String code = CodeUtil.generateCode(serialNum, coupon.getId());
            ExchangeCode exchangeCode = new ExchangeCode();
            exchangeCode.setCode(code);
            exchangeCode.setId(serialNum);
            exchangeCode.setExchangeTargetId(coupon.getId());
            exchangeCode.setExpiredTime(coupon.getIssueEndTime());
            list.add(exchangeCode);
        }
        saveBatch(list);

        //写入到redis缓存member:couponId,score:兑换码最大序列号
        redisTemplate.opsForZSet().add(COUPON_RANGE_KEY,coupon.getId().toString(),maxSerialNum);
    }

    @Override
    public Result queryCouponByPage(CouponQuery query) {
        Integer codeStatus = query.getCodeStatus();
        Page<ExchangeCode> page = new Page<>(query.getPage(), query.getSize());
        Page<ExchangeCode> paged = lambdaQuery().eq(codeStatus != null, ExchangeCode::getStatus, codeStatus)
                .orderByDesc(ExchangeCode::getCreateTime)
                .page(page);
        List<ExchangeCode> records = paged.getRecords();
        return Result.success(records);
    }

    @Override
    public boolean updateExchangeMark(long serialNum, boolean b) {
        Boolean boo = redisTemplate.opsForValue().setBit(COUPON_CODE_MAP_KEY, serialNum, b);
        return boo !=null && boo;
    }
}
